package com.zbj.homemade.spring.context;

import com.zbj.homemade.spring.ApplicationContext;
import com.zbj.homemade.spring.BeanFactory;
import com.zbj.homemade.spring.SimpleBeanFactory;
import com.zbj.homemade.spring.beans.BeanDefinition;
import com.zbj.homemade.spring.beans.BeanDefinitionRegistry;
import com.zbj.homemade.spring.beans.SimpleBeanDefinition;
import com.zbj.homemade.spring.factorylifecycle.BeanDefinitionRegistryPostProcessor;
import com.zbj.homemade.spring.factorylifecycle.BeanFatoryPostProcessor;
import com.zbj.homemade.spring.factorylifecycle.ConfigurationClassPostProcessor;
import com.zbj.homemade.spring.lifecycle.BeanPostProcessor;
import com.zbj.homemade.spring.scan.AnnotatedBeanDefinitionReader;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * |                    .  ’   *   ‘  .
 * |               _6                    "     o0000o
 * |  o00o _    .%                         %. o0000000o
 * | o000000o.:                              :(0000000o
 * | o00000os                                  .000000o
 * |  o0000/     <b>不了不了,改需求真的伤身体</>   .000o
 * |    o0o                                       .0o
 * |     y        <b>我认为源代码,就是SkrSkr</>     .
 * |    y                                           ,
 * |   y          <b>小熊猫保佑,代码永不修改</>        ,
 * |   p                            .                 .
 * |   p                           @@.                .
 * |    y                        ;@@@;               .
 * |    \                       ;@@@@;.@.          ,;S
 * |     、                     .@@@@@@;       ,@@@@@
 * |     @\.            .****...*@@@@;     .@@@@@@@@@@@.
 * |    @@@@\.     . @@@@@@@@@@@@@@@;    .@@@@@@@@@@@@@@@.
 * |   @@@@@@@@@.@@@@@@@@@@@@@@@@;   .@@@@@@@@@@@@@@@@@@@@@.
 * |  @@@@@@..@@@@..@@@@@@..@@@@@ .@@...@@@@@..@@..@@@@@..@@.
 * | @@@@@@@@..@..@@@@@@@@@@@@@;.@@@..@..@@@..@@....@@@..@@@@.
 * |@y@@@@@@@@..@@@@@@@@..@@@@i@@@@..@@@..@..@@..@@..@..@@@@n@.
 * |@n@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@...@@..@@@@...@@@@@n@@.
 * |@@@@@@@@..@@@@@@@@..@@@@@@@@@..@@@@@@@.@@..@@@@@..@@@@@@@@@@.
 * |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.
 *
 * @program: principle
 * @description:
 * @author: Yinn
 * @create: 2019-03-01 15:31
 **/
public class SimpleApplacationContext implements BeanDefinitionRegistry, ApplicationContext, AnnotationConfigRegistry {

    /**
     * bean factory 指针
     */
    private SimpleBeanFactory beanFactory;

    /**
     * 初始化bean定义解析
     */
    private AnnotatedBeanDefinitionReader reader;

    /**
     * 工厂级别后置处理器
     */
    private final List<BeanFatoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();

    public SimpleApplacationContext() {
        this.beanFactory = new SimpleBeanFactory();
        this.reader = new AnnotatedBeanDefinitionReader(this);
    }

    /**
     * 注解启动实现方式
     */
    public SimpleApplacationContext(Class<?> configClazz) {
        this();
        register(configClazz);
        refresh();
    }

    /**
     * 在此例中，我们只实现一些必要功能，下述注释是spring源码中的必要步骤，在spring中，研究容器也是按照此步骤来，其中
     * 第11步尤为重要！！！
     * <p>
     * 原始app上下文refresh方法步骤:
     * 1. Prepare this context for refreshing.
     * 翻译: 为刷新做准备
     * 白话：设置时间，初始化各种properties，初始化各种系统变量，例如os.name之类的变量
     * <p>
     * 2. Tell the subclass to refresh the internal bean factory.
     * 翻译：通知子类（因为refresh方法在AbstractApplicationContext下）刷新内部bean工厂引用。
     * 白话：就是new了个bean工厂出来，然后把指针扔进了appcontext内部变量里
     * <p>
     * 3. Prepare the bean factory for use in this context.
     * 翻译：准备bean工厂
     * 白话：就是对bean工厂配置一些属性，例如要忽略什么，有什么后置处理器
     * <p>
     * 4. Allows post-processing of the bean factory in context subclasses.
     * 翻译：允许在子类中后置处理bean工厂
     * 白话：此方法为空，子类自己实现
     * <p>
     * 5. Invoke factory processors registered as beans in the context.
     * 翻译：执行注册在上下文内部的{beanFactoryPostProcessor}
     * (初始化所有bean定义就是在这一步的ConfigurationClassPostProcessor里执行的。)
     * <p>
     * 6. Register bean processors that intercept bean creation.
     * 翻译：注册bean级别后置处理器{BeanPostProcessor}
     * <p>
     * 7. Initialize message source for this context.
     * 翻译:初始化上下文中信息资源（做国际化功能；消息绑定，消息解析）；
     * <p>
     * 8. Initialize event multicaster for this context.
     * 翻译：初始化时间派发器
     * <p>
     * 9. Initialize other special beans in specific context subclasses.
     * 翻译：在子app类中，自己实现一些初始化特别bean的方法。
     * 白话：留给你自己继承AbstractApplicationContext
     * <p>
     * 10. Check for listener beans and register them.
     * 翻译：检查并注册监听器s。
     * <p>
     * ★！！！11. Instantiate all remaining (non-lazy-init) singletons.
     * 翻译：实例化所有单例非懒加载的bean！！
     * 十分重要！！！
     * <p>
     * 12. Last step: publish corresponding event.
     * 翻译：发布事件
     */
    @Override
    public void refresh() {

        //3 5合并
        preAndExecBeanFactoryPostProcessor();

        //5 注册bean后置处理器
        registerBeanPostProcessors(beanFactory);

        //11.实例化所有单例.
        finishBeanFactoryInitialization(beanFactory);

    }

    protected void preAndExecBeanFactoryPostProcessor() {

        //只是展示过程 排序就不展示了 ,搞一个order接口 用list的sort去实现就好
        //准备工厂级别后置处理器
//        this.beanFactoryPostProcessors.add(new ConfigurationClassPostProcessor());
        addBeanFactoryPostProcessor(new ConfigurationClassPostProcessor());
        List<String> postProcessorNames = beanFactory.getBeanNamesByType(BeanFatoryPostProcessor.class);

        //实例化所有beanFactoryPostProcessor 并丢入处理链中
        if (postProcessorNames != null && postProcessorNames.size() > 0) {
            for (String postProcessorName : postProcessorNames) {
                BeanFatoryPostProcessor sbd = (BeanFatoryPostProcessor) getBean(postProcessorName);

                if (sbd != null)
                    addBeanFactoryPostProcessor(sbd);
            }
        }


        //bean定义注册器后置处理器
        for (BeanFatoryPostProcessor beanFatoryPostProcessor : this.beanFactoryPostProcessors) {

            if (beanFatoryPostProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor bdrpp = (BeanDefinitionRegistryPostProcessor) beanFatoryPostProcessor;
                bdrpp.postProcessBeanDefinitionRegistry(this);
            }
        }

        //工厂后置处理器
        for (BeanFatoryPostProcessor beanFatoryPostProcessor : this.beanFactoryPostProcessors) {
            beanFatoryPostProcessor.postProcessBeanFactory(this.beanFactory);
        }
    }

    /**
     * 注册所有bean级别后置处理器
     */
    protected void registerBeanPostProcessors(SimpleBeanFactory beanFactory) {
        List<String> postProcessorNames = beanFactory.getBeanNamesByType(BeanPostProcessor.class);

        //实例化所有BeanPostProcessor 并丢入处理链中
        if (postProcessorNames != null && postProcessorNames.size() > 0) {
            for (String postProcessorName : postProcessorNames) {
                BeanPostProcessor sbd = (BeanPostProcessor) getBean(postProcessorName);

                if (sbd != null)
                    addBeanPostProcessor(sbd);
            }
        }

    }

    /**
     * bean工厂完成初始化方法，完成所有bean的初始化.
     */
    protected void finishBeanFactoryInitialization(SimpleBeanFactory beanFactory) {
        beanFactory.preInstantiateSingletons();
    }

    @Override
    public <T> T getBean(Class<T> clazz) {
        return this.beanFactory.getBean(clazz);
    }

    @Override
    public Object getBean(String name) {
        return this.beanFactory.getBean(name);
    }

    @Override
    public void start() {
    }

    @Override
    public void stop() {
        //只展示disposeableBean
        beanFactory.destory();
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor postProcessor) {
        beanFactory.addBeanPostProcessor(postProcessor);
    }

    public void addBeanFactoryPostProcessor(BeanFatoryPostProcessor beanFatoryPostProcessor) {
        this.beanFactoryPostProcessors.add(beanFatoryPostProcessor);
    }

    @Override
    public void scan(String... basePackages) {
        //就是xml配置扫描的方式
    }

    @Override
    public void register(Class<?>... annotatedClasses) {
        //根据@Configuration注解配置spring
        //注册配置类
        this.reader.register(annotatedClasses);
    }

    // todo bean工厂实现 注册bean定义
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        beanFactory.registerBeanDefinition(beanName, beanDefinition);
    }

    @Override
    public void removeBeanDefinition(String beanName) {
        beanFactory.removeBeanDefinition(beanName);
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return beanFactory.getBeanDefinition(beanName);
    }

    @Override
    public boolean containsBeanDefinition(String beanName) {
        return beanFactory.containsBeanDefinition(beanName);
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return beanFactory.getBeanDefinitionNames();
    }

    @Override
    public int getBeanDefinitionCount() {
        return beanFactory.getBeanDefinitionCount();
    }
}
